package com.ikingtech.platform.service.office.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.type.TypeReference;
import com.ikingtech.framework.sdk.context.exception.FrameworkException;
import com.ikingtech.framework.sdk.core.response.R;
import com.ikingtech.framework.sdk.office.model.dto.OfficeDataFieldsDto;
import com.ikingtech.framework.sdk.office.model.dto.OfficeDataManagementDto;
import com.ikingtech.framework.sdk.office.model.dto.OfficeDataParamsDto;
import com.ikingtech.framework.sdk.office.model.enums.OfficeDataEnums;
import com.ikingtech.framework.sdk.office.model.query.OfficeDataManagementQuery;
import com.ikingtech.framework.sdk.office.model.vo.OfficeDataFieldsVo;
import com.ikingtech.framework.sdk.office.model.vo.OfficeDataManagementVo;
import com.ikingtech.framework.sdk.office.model.vo.OfficeDataParamsVo;
import com.ikingtech.framework.sdk.office.properties.OfficeProperties;
import com.ikingtech.framework.sdk.utils.Tools;
import com.ikingtech.platform.service.office.entity.OfficeDataFields;
import com.ikingtech.platform.service.office.entity.OfficeDataManagement;
import com.ikingtech.platform.service.office.entity.OfficeDataParams;
import com.ikingtech.platform.service.office.mapper.OfficeDataFieldsMapper;
import com.ikingtech.platform.service.office.mapper.OfficeDataManagementMapper;
import com.ikingtech.platform.service.office.mapper.OfficeDataParamsMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 办公文件管理-基础数据管理 服务实现类
 * </p>
 *
 * @author lqb
 */
@Slf4j
@RequiredArgsConstructor
public class OfficeDataManagementService extends ServiceImpl<OfficeDataManagementMapper, OfficeDataManagement> {

    private final OfficeDataFieldsMapper officeDataFieldsMapper;
    private final OfficeDataParamsMapper officeDataParamsMapper;
    private final OfficeProperties officeProperties;

    /**
     * 添加
     *
     * @param dto 到
     * @return 执行结果
     * @author lqb
     */
    @Transactional(rollbackFor = Exception.class)
    public R<String> add(OfficeDataManagementDto dto) {
        OfficeDataManagement management = dto.copy(new OfficeDataManagement(), "id", "paramsList", "fieldsList");
        management.setSortOrder(this.baseMapper.getMaxSortOrder(dto.getBusinessType()))
                .setDelFlag(Boolean.FALSE)
                .setId(Tools.Id.uuid());
        management.insert();

        this.saveParams(management.getId(), dto.getFields(), dto.getParams());
        return R.ok();
    }

    /**
     * 保存参数
     *
     * @param managementId 管理id
     * @param fieldList    字段列表
     * @param paramList    参数列表
     */
    private void saveParams(String managementId, List<OfficeDataFieldsDto> fieldList, List<OfficeDataParamsDto> paramList) {
        // 删除旧数据
        officeDataFieldsMapper.delete(new QueryWrapper<OfficeDataFields>().lambda()
                .eq(OfficeDataFields::getDataBaseManagementId, managementId));
        officeDataParamsMapper.delete(new QueryWrapper<OfficeDataParams>().lambda()
                .eq(OfficeDataParams::getDataBaseManagementId, managementId));

        // 返回字段
        if (ObjectUtils.isNotEmpty(fieldList)) {
            fieldList.forEach(f -> {
                OfficeDataFields fields = f.copy(new OfficeDataFields());
                fields.setDataBaseManagementId(managementId)
                        .setDelFlag(Boolean.FALSE)
                        .setId(Tools.Id.uuid());
                fields.insert();
            });
        }

        // 请求参数
        if (ObjectUtils.isNotEmpty(paramList)) {
            paramList.forEach(p -> {
                OfficeDataParams params = p.copy(new OfficeDataParams());
                params.setDataBaseManagementId(managementId)
                        .setDelFlag(Boolean.FALSE)
                        .setId(Tools.Id.uuid());
                params.insert();
            });
        }

    }

    /**
     * 使现代化
     *
     * @param dto 到
     * @return 执行结果
     */
    @Transactional(rollbackFor = Exception.class)
    public R<String> update(OfficeDataManagementDto dto) {
        OfficeDataManagement management = dto.copy(new OfficeDataManagement(), "paramsList", "fieldsList");
        management.setSortOrder(this.baseMapper.getMaxSortOrder(dto.getBusinessType()))
                .setDelFlag(Boolean.FALSE)
                .setId(Tools.Id.uuid());
        management.updateById();
        this.saveParams(management.getId(), dto.getFields(), dto.getParams());
        return R.ok();
    }

    /**
     * 查询列表
     *
     * @param query 查询
     * @return 执行结果
     */
    public R<List<OfficeDataManagementVo>> queryList(OfficeDataManagementQuery query) {
        List<OfficeDataManagementVo> list = this.baseMapper.queryList(query);
        return R.ok(list);
    }

    /**
     * 详细信息
     *
     * @author lqb
     * @since 2023/09/19
     */
    public R<OfficeDataManagementVo> details(String id) {
        OfficeDataManagement management = this.getById(id);
        if (ObjectUtils.isEmpty(management)) {
            throw new FrameworkException("数据未找到");
        }
        OfficeDataManagementVo data = management.copy(new OfficeDataManagementVo());
        this.buildDataInfo(data);
        return R.ok(data);

    }

    private void buildDataInfo(OfficeDataManagementVo data) {
        data.setParams(
                        officeDataParamsMapper.selectList(new QueryWrapper<OfficeDataParams>().lambda()
                                .eq(OfficeDataParams::getDataBaseManagementId, data.getId())
                                .orderByAsc(OfficeDataParams::getSortOrder)
                        ).stream().map(param -> param.copy(new OfficeDataParamsVo())).collect(Collectors.toList()))
                .setFields(
                        officeDataFieldsMapper.selectList(new QueryWrapper<OfficeDataFields>().lambda()
                                .eq(OfficeDataFields::getDataBaseManagementId, data.getId())
                                .orderByAsc(OfficeDataFields::getSortOrder)
                        ).stream().map(field -> field.copy(new OfficeDataFieldsVo())).collect(Collectors.toList()));
    }

    /**
     * 预览
     *
     */
    public R<Object> preview(String id, Map<String, Object> params) {
        // 获取详情
        OfficeDataManagementVo details = this.details(id).getData();
        // json
        if (OfficeDataEnums.ResourceType.JSON.equals(details.getResourceType())) {
            return R.ok(Tools.Json.toMap(details.getContent()));
        } else if (OfficeDataEnums.ResourceType.API.equals(details.getResourceType())) {
            // api
            String resultStr = "";
            StringBuilder uri = new StringBuilder();
            uri.append(this.officeProperties.getCallBackUrl())
                    .append(details.getService())
                    .append(details.getContent());
            // 参数
            Map<String, Object> paramMap = new HashMap<>();
            for (OfficeDataParamsVo p : details.getParams()) {
                // 没有默认参数
                if (StringUtils.isNotBlank(p.getParamValue())) {
                    paramMap.put(p.getParamKey(), p.getParamValue());
                } else if (params.containsKey(p.getParamKey())) {
                    // 给参数赋值
                    paramMap.put(p.getParamKey(), params.get(p.getParamKey()));
                }
            }
            if (OfficeDataEnums.ApiMethod.GET.equals(details.getApiMethod())) {
                if (ObjectUtils.isNotEmpty(paramMap)) {
                    uri.append(Tools.Http.QUERY_PARAM_CONNECT)
                            .append(Tools.Http.toQueryStr(paramMap));
                }
                log.info(uri.toString());
                resultStr = Tools.Http.get(uri.toString());
            } else if (OfficeDataEnums.ApiMethod.POST.equals(details.getApiMethod())) {
                String postParams = "";
                if (ObjectUtils.isNotEmpty(paramMap)) {
                    postParams = Tools.Json.toJsonStr(paramMap);
                }
                log.info("url: {} params:{}", uri, postParams);
                resultStr = Tools.Http.post(uri.toString(), postParams);
            }
            log.info(resultStr);
            if (StringUtils.isBlank(resultStr)) {
                return R.failed("预览数据失败");
            }
            return Tools.Json.toBean(resultStr, new TypeReference<R<Object>>() {
            });
        }
        return R.failed("预览数据失败");
    }
}

